package org.zjvis.graph.analysis.service.exception.handler;

import cn.hutool.core.exceptions.ExceptionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.zjvis.datascience.common.graph.model.GraphDataCheckException;
import org.zjvis.graph.analysis.service.exception.GraphAnalysisException;
import org.zjvis.graph.analysis.service.model.util.ApiResult;
import org.zjvis.graph.analysis.service.enums.ApiResultCode;


import java.util.Objects;

/**
 * @description 处理异常
 * @date 2020-02-23
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    private final static Logger logger = LoggerFactory.getLogger("GlobalExceptionHandler");
    public static final int EXCEPTION_INFO_LIMIT = 100000;

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(value = GraphAnalysisException.class)
    public ResponseEntity<ApiResult> badRequestException(GraphAnalysisException e) {
        // 打印堆栈信息
        logger.error(e.getMessage(), e);
        if (e.getCause() != null) {
            e.getApiResult().setTips(ExceptionUtil.stacktraceToString(e, EXCEPTION_INFO_LIMIT));
        }
        return buildResponseEntity(HttpStatus.OK, e.getApiResult());
    }

    /**
     * 处理所有接口数据验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ApiResult> handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        // 打印堆栈信息
        logger.error(e.getMessage(), e);
        String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
        String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
        String msg = "不能为空";
        if (msg.equals(message)) {
            message = str[1] + ":" + message;
        }
        return buildResponseEntity(HttpStatus.BAD_REQUEST, ApiResult.valueOf(ApiResultCode.PARAM_ERROR, message));
    }

    /**
     * 处理所有不可知的异常
     */
    @ExceptionHandler(value = Throwable.class)
    public ResponseEntity<ApiResult> handleException(Throwable e) {
        // 打印堆栈信息
        logger.error(e.getMessage(), e);
        return buildResponseEntity(HttpStatus.INTERNAL_SERVER_ERROR, ApiResult.valueOf(ApiResultCode.SYS_ERROR, e.getMessage())
        );
    }

    @ExceptionHandler(value = MissingServletRequestParameterException.class)
    public ResponseEntity<ApiResult> handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
        logger.error(e.getMessage(), e);
        return buildResponseEntity(HttpStatus.BAD_REQUEST, ApiResult.valueOf(ApiResultCode.PARAM_ERROR, e.getMessage())
        );
    }

    @ExceptionHandler(value = GraphDataCheckException.class)
    public ResponseEntity<ApiResult> handleGraphDataCheckException(GraphDataCheckException e) {
        logger.error(e.getMessage(), e);
        String info;
        if (e.getInfo() == null || e.getInfo().isEmpty()) {
            info = e.getCode().getMsg();
        } else {
            info = e.getCode().getMsg() + ": " + e.getInfo();
        }
        return buildResponseEntity(HttpStatus.OK, new ApiResult(e.getCode().getCode(), info));
    }

    /**
     * 统一返回
     *
     * @param httpStatus
     * @param apiResult
     * @return
     */
    private ResponseEntity<ApiResult> buildResponseEntity(HttpStatus httpStatus, ApiResult apiResult) {
        if (apiResult.getResult() != null && apiResult.getResult() instanceof String) {
            apiResult.setMessage(apiResult.getMessage() + " " + apiResult.getResult());
        }
        return new ResponseEntity<>(apiResult, httpStatus);
    }

}
